#define ZCORE_SOURCE
#include "XML.hpp"

#ifdef ZZZ_LIB_TINYXML
#define TIXML_USE_STL
#include <tinyxml/tinyxml.h>
#include <tinyxml/tinystr.h>
namespace zzz{
bool XML::LoadFile(const string &filename)
{
  filename_=filename;
  bool res=doc_->LoadFile(filename);
  if (doc_->Error())
  {
    printf("Error in %s: %s\n", doc_->Value(), doc_->ErrorDesc());
    return false;
  }
  return res;
}

bool XML::SaveFile(const string &filename)
{
  if (doc_->Error())
  {
    printf("Error in %s: %s\n", doc_->Value(), doc_->ErrorDesc());
    return false;
  }
  filename_=filename;
  return doc_->SaveFile(filename);
}


//children
zuint XML::NodeNumber() const
{
  zuint x=0;
  for (const TiXmlNode *pChild=doc_->FirstChild();pChild!=0;pChild=pChild->NextSibling())
    if (pChild->Type()==TiXmlNode::TINYXML_ELEMENT) x++;
  return x;
}

XMLNode XML::GetNode(zuint i)
{
  zuint x=-1;
  for (TiXmlNode *pChild=doc_->FirstChild();pChild!=0;pChild=pChild->NextSibling())
  {
    if (pChild->Type()==TiXmlNode::TINYXML_ELEMENT) x++;
    if (x==i) return XMLNode(pChild->ToElement(),this);
  }
  ZLOGF<<"Node "<<i<<" does not exist!";
  return XMLNode(NULL,this);
}

XMLNode XML::GetNode(const string &name)
{
  for (TiXmlNode *pChild=doc_->FirstChild();pChild!=0;pChild=pChild->NextSibling())
  {
    if (pChild->Type()==TiXmlNode::TINYXML_ELEMENT && name == pChild->Value()) return XMLNode(pChild->ToElement(),this);
  }
  ZLOGF<<"Node "<<name<<" does not exist!";
  return XMLNode(NULL,this);
}

bool XML::HasNode(const string &name)
{
  for (TiXmlNode *pChild=doc_->FirstChild();pChild!=0;pChild=pChild->NextSibling())
  {
    if (pChild->Type()==TiXmlNode::TINYXML_ELEMENT && name == pChild->Value()==0) return true;
  }
  return false;
}

XMLNode XML::AppendNode(const string &name)
{
  if (NodeNumber()==0)
    doc_->LinkEndChild(new TiXmlDeclaration("1.0", "", ""));
  TiXmlElement *element=new TiXmlElement(name);
  doc_->LinkEndChild(element);
  return XMLNode(element,this);
}

bool XML::RemoveNode(const string &name)
{
  for (TiXmlNode *pChild=doc_->FirstChild();pChild!=0;pChild=pChild->NextSibling())
  {
    if (name == pChild->Value()) 
    {
      doc_->RemoveChild(pChild);
      return true;
    }
  }
  return false;
}

bool XML::RemoveNode(zuint i)
{
  zuint x=0;
  for (TiXmlNode *pChild=doc_->FirstChild();pChild!=0;pChild=pChild->NextSibling(), x++)
  {
    if (x==i)    
    {
      doc_->RemoveChild(pChild);
      return true;
    }

  }
  return false;
}

const string& XML::GetFilename() const
{
  return filename_;
}

XML::~XML()
{
  delete doc_;
}

XML::XML()
{
  doc_=new TiXmlDocument;
}

}
#endif // ZZZ_LIB_TINYXML
